package com.huiyang.demo.service;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

import com.huiyang.demo.entity.DeviceInfoEntity;
import com.huiyang.demo.utils.JsonBuilder;

import org.json.JSONException;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

/**
 * @ProjectName: DEEBCG Websoket Demo
 * @Package: huiyang.supervise.bed.service
 * @ClassName: WebSocketService
 * @Description: websocket长连接+心跳检测
 * @Author: yuan
 * @CreateDate: 2020/8/31 1:34 PM
 */
public class WebSocketService extends Service {

    //socket 地址
    private static final String WEBSOCKET_HOST_AND_PORT = "wss://socket.deebcg.cn/";
    // 心跳检测时间
    private static final long HEART_BEAT_RATE = 30 * 1000;//每隔60秒进行一次对长连接的心跳检测

    private WebSocket mWebSocket;

    private long sendTime = 0L;
    // 发送心跳包
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    new InitSocketThread().start();
                    break;
                case 2:
                    if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                        tryReconnect();
                    }
                    mHandler.sendEmptyMessageDelayed(2, HEART_BEAT_RATE);//每隔一定的时间，对长连接进行一次心跳检测
                    break;

            }
        }
    };

    private IWebSocketResponseListener responseListener = null;

    public void setResponseListener(IWebSocketResponseListener responseListener) {
        this.responseListener = responseListener;
    }

    //设备编号
    static String EquipmentNumber = "";
    public void setEquipmentNumber(String  id) {
        this.EquipmentNumber = id;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        new InitSocketThread().start();
        return new MyBinder();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }


    public void closeSocket() {
        if (mWebSocket != null) {
            mHandler.removeCallbacks(heartBeatRunnable);
            mWebSocket.close(1000, null);
        }
    }

    public void againLoginConnection(String id) {
        Log.i("websocket", "websocket---重连");
        EquipmentNumber = id;
        tryReconnect();
    }

    class InitSocketThread extends Thread {
        @Override
        public void run() {
            super.run();
            try {
                initSocket();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    DeviceInfoEntity deviceInfo = null;

    // 初始化socket
    private void initSocket() throws UnknownHostException, IOException {
        OkHttpClient client = new OkHttpClient.Builder()
                .readTimeout(0, TimeUnit.MILLISECONDS)
                .build();
        Request request = new Request.Builder()
                .header("Origin", "android")
                .url(WEBSOCKET_HOST_AND_PORT)
                .build();
        client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {//开启长连接成功的回调
                super.onOpen(webSocket, response);
                mWebSocket = webSocket;
                Log.i("websocket", "onOpen---" + response.toString());
                //连接成功 发送用户名和密码
                sendLoginMessage();
                mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//开启心跳监测
                if (responseListener != null) {
                    responseListener.onSocketStatus("服务器已连接");
                }
            }


            @Override
            public void onMessage(WebSocket webSocket, final String text) {//接收消息的回调
                super.onMessage(webSocket, text);
                //收到服务器端传过来的消息text
                sendTime = System.currentTimeMillis();
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    mHandler.post(() -> {
                        deviceInfo = DeviceInfoEntity.parseData(text);//解析数据
                        if (deviceInfo != null && deviceInfo.getMsgType().equals("PingMessage")) {
                        } else {
                            if (responseListener != null) {
                                responseListener.onMessageText(deviceInfo);
                            }
                        }
                    });
                }

            }

            @Override
            public void onMessage(WebSocket webSocket, ByteString bytes) {
                super.onMessage(webSocket, bytes);
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    mHandler.post(() -> Log.e("websocket", "WsManager-----onMessage"));
                } else {
                    Log.e("websocket", "WsManager-----onMessage");
                }
            }

            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                super.onClosing(webSocket, code, reason);
                if (responseListener != null) {
                    responseListener.onSocketStatus("服务器连接关闭中");
                }
            }

            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                super.onClosed(webSocket, code, reason);

                if (responseListener != null) {
                    responseListener.onSocketStatus("服务器连接已关闭");
                }

            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, @Nullable Response response) {//长连接连接失败的回调
                super.onFailure(webSocket, t, response);
                if (responseListener != null) {
                    responseListener.onSocketStatus("服务器连接失败");
                }
            }
        });

        client.dispatcher().executorService().shutdown();
    }

    /**
     * 发送登陆、波形命令
     */
    public void sendLoginMessage() {
        sendMessageString(compoundLoginJsonStr());
        sendMessageString(compoundChartJsonStr());
    }

    public boolean sendMessageString(String message) {
        if (mWebSocket != null)
            return mWebSocket.send(message);
        else return false;
    }

    public static String compoundLoginJsonStr() {
        try {
            JsonBuilder count = new JsonBuilder();
            count.append("type", "DeviceInfo");
            count.append("mac", EquipmentNumber);
            return count.builder().toString();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String compoundChartJsonStr() {
        try {
            JsonBuilder count = new JsonBuilder();
            count.append("type", "ViewData");
            count.append("mac", EquipmentNumber);
            return count.builder().toString();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "";
    }

    private void tryReconnect() {
        Log.e("websocket", "websocket  重连");
        mHandler.removeCallbacks(heartBeatRunnable);
        if (mWebSocket != null)
            mWebSocket.cancel();//取消掉以前的长连接
        mHandler.sendEmptyMessage(1);//创建一个新的连接
        if (responseListener != null) {
            responseListener.onSocketStatus("服务器重连");
        }
    }


    private Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                tryReconnect();
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);//每隔一定的时间，对长连接进行一次心跳检测
        }
    };

    public class MyBinder extends Binder {
        public WebSocketService getService() {
            return WebSocketService.this;
        }

        @Override
        protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
            return super.onTransact(code, data, reply, flags);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        closeSocket();
    }
}
